
import java.util.ArrayList;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.BoxLayout;

import poker.gui.PokerFrame;


class MyCursor {
	public int id; // identifier

	// This stores the history of positions of the "cursor" (finger)
	// in pixel coordinates.
	// The first position is where the finger pressed down,
	// and the last position is the current position of the finger.
	private ArrayList< Point2D > positions = new ArrayList< Point2D >();

	private float totalDistanceAlongDrag = 0;
	private float distanceFromStartToEndOfDrag = 0;

	public MyCursor( int id, float x, float y ) {
		this.id = id;
		positions.add( new Point2D(x,y) );
	}

	public ArrayList< Point2D > getPositions() { return positions; }

	public void addPosition( Point2D p ) {
		if ( positions.size() >= 1 ) {
			totalDistanceAlongDrag += p.distance( positions.get(positions.size()-1) );
			distanceFromStartToEndOfDrag = p.distance( positions.get(0) );
		}
		positions.add( p );
	}

	public Point2D getCurrentPosition() {
		if ( positions == null || positions.size() < 1 )
			return null;
		return positions.get( positions.size()-1 );
	}
	public Point2D getPreviousPosition() {
		if ( positions == null || positions.size() == 0 )
			return null;
		if ( positions.size() == 1 )
			return positions.get( 0 );
		return positions.get( positions.size()-2 );
	}

	public boolean doesDragLookLikeLassoGesture() {
		return totalDistanceAlongDrag / (float)distanceFromStartToEndOfDrag > 2.5f;
	}
}

class MyCursorContainer {
	private ArrayList< MyCursor > cursors = new ArrayList< MyCursor >();

	public int getNumCursors() { return cursors.size(); }
	public MyCursor getCursorByIndex( int index ) { return cursors.get( index ); }

	public int findIndexOfCursorById( int id ) {
		for ( int i = 0; i < cursors.size(); ++i ) {
			if ( cursors.get(i).id == id )
				return i;
		}
		return -1;
	}
	public MyCursor getCursorById( int id ) {
		int index = findIndexOfCursorById( id );
		return ( index == -1 ) ? null : cursors.get( index );
	}
	// returns index of updated cursor
	public int updateCursorById(
		int id,
		float x, float y
	) {
		Point2D updatedPosition = new Point2D( x, y );
		int index = findIndexOfCursorById( id );
		if ( index == -1 ) {
			cursors.add( new MyCursor( id, x, y ) );
			index = cursors.size() - 1;
		}
		MyCursor c = cursors.get( index );
		if ( ! c.getCurrentPosition().equals( updatedPosition ) ) {
			c.addPosition( updatedPosition );
		}
		return index;
	}
	public void removeCursorByIndex( int index ) {
		cursors.remove( index );
	}
	public ArrayList< Point2D > getWorldPositionsOfCursors( GraphicsWrapper gw ) {
		ArrayList< Point2D > positions = new ArrayList< Point2D >();
		for ( MyCursor cursor : cursors ) {
			positions.add( gw.convertPixelsToWorldSpaceUnits( cursor.getCurrentPosition() ) );
		}
		return positions;
	}
}



public class SimpleMultitouchPokerGame implements Runnable, ActionListener {

	public MultitouchFramework multitouchFramework = null;
	public GraphicsWrapper gw = null;
	JMenuItem testMenuItem1;
	JMenuItem testMenuItem2;
	JCheckBox autoZoomCheckBox;
	JCheckBox cameraModeCheckBox;
	JCheckBox pauseCheckBox;
	boolean isAutoZoomEnabled = true;
	boolean isCameraModeActive = false;
	boolean isGamePaused = false;
	JButton frameAllButton;
	JButton testButton1;
	JButton testButton2;
	PokerFrame pokerFrame;
	Thread thread = null;
	boolean threadSuspended;


	MyCursorContainer cursorContainer = new MyCursorContainer();
	int mouse_x, mouse_y;

	public SimpleMultitouchPokerGame( MultitouchFramework mf, GraphicsWrapper gw, PokerFrame pf ) {
		pokerFrame = pf;
		multitouchFramework = mf;
		this.gw = gw;
		multitouchFramework.setPreferredWindowSize(Constant.INITIAL_WINDOW_WIDTH,Constant.INITIAL_WINDOW_HEIGHT);
		gw.setFontHeight( Constant.TEXT_HEIGHT );
		//gw.frame( game.getBoundingRectangle(), true );
	}

	

	// Called by the framework at startup time.
	public void startBackgroundWork() {
		if ( thread == null ) {
			thread = new Thread( this );
			threadSuspended = false;
			thread.start();
		}
		else {
			if ( threadSuspended ) {
				threadSuspended = false;
				synchronized( this ) {
					notify();
				}
			}
		}
	}
	
	public void run() {
		try {
			int sleepIntervalInMilliseconds = 25;
			int timeSinceLastAutoZoomInMilliseconds = 0;
			while (true) {

				// Here's where the thread does some work
				synchronized( this ) {
					if ( ! isGamePaused ) {
						//game.advanceTimeStep();
						if ( isAutoZoomEnabled && ! isCameraModeActive ) {
							timeSinceLastAutoZoomInMilliseconds += sleepIntervalInMilliseconds;
							if ( timeSinceLastAutoZoomInMilliseconds>=5000 && cursorContainer.getNumCursors()==0 ) {
//								AlignedRectangle2D rectangle = game.getBoundingRectangle();
//
//								// if the rectangle is very small, make it bigger
//								final float minSize = 20 * Constant.SOLDIER_RADIUS;
//								if ( rectangle.getDiagonal().x() < minSize || rectangle.getDiagonal().y() < minSize ) {
//									Point2D p = rectangle.getCenter();
//									rectangle.bound( Point2D.sum(p,new Vector2D( minSize/2,0)) );
//									rectangle.bound( Point2D.sum(p,new Vector2D(-minSize/2,0)) );
//									rectangle.bound( Point2D.sum(p,new Vector2D(0, minSize/2)) );
//									rectangle.bound( Point2D.sum(p,new Vector2D(0,-minSize/2)) );
//								}

								//gw.frame( rectangle, true );
								timeSinceLastAutoZoomInMilliseconds = 0;
							}
						}
					}
				}
				multitouchFramework.requestRedraw();

				// Now the thread checks to see if it should suspend itself
				if ( threadSuspended ) {
					synchronized( this ) {
						while ( threadSuspended ) {
							wait();
						}
					}
				}
				thread.sleep( sleepIntervalInMilliseconds );  // interval given in milliseconds
			}
		}
		catch (InterruptedException e) { }
	}

	
	public void stopBackgroundWork() {
		threadSuspended = true;
	}
	

	public synchronized void draw() {
		//gw.clear(1,1,1);
		//gw.setColor(255,255,0);
		//gw.setupForDrawing();

//		gw.setCoordinateSystemToWorldSpaceUnits();
		//gw.enableAlphaBlending();

		// draw the armies
		//game.draw( gw );
		pokerFrame.repaint();
//		gw.setCoordinateSystemToPixels();
//
//		// draw cursors
//		for ( int i = 0; i < cursorContainer.getNumCursors(); ++i ) {
//			MyCursor cursor = cursorContainer.getCursorByIndex( i );
//			gw.setColor(0,0.5f,0.5f,0.65f);
//			gw.fillCircle( cursor.getCurrentPosition().x()-10, cursor.getCurrentPosition().y()-10, 10 );
//			if ( ! isCameraModeActive ) {
//				if ( cursor.doesDragLookLikeLassoGesture() ) {
//					// draw polygon
//					gw.setColor(0,0,0,0.2f);
//					gw.fillPolygon( cursor.getPositions() );
//				}
//				else {
//					// draw ink trail
//					gw.setColor(0,0,0);
//					gw.drawPolyline( cursor.getPositions() );
//				}
//			}
//		}

		// draw some text
//		if ( cursorContainer.getNumCursors() > 0 ) {
//			gw.setFontHeight( Constant.TEXT_HEIGHT );
//			String s = "[" + cursorContainer.getNumCursors() + " contacts]";
//			System.out.println(s);
//			gw.drawString(
//				Constant.TEXT_HEIGHT,
//				2 * Constant.TEXT_HEIGHT,
//				s
//			);
//		}
		

	}

	public synchronized void keyPressed( KeyEvent e ) {
		System.out.println("Key '" + e.getKeyChar() + "' pressed!");
	}
	public synchronized void keyReleased( KeyEvent e ) {
	}
	public synchronized void keyTyped( KeyEvent e ) {
		System.out.println("Key '" + e.getKeyChar() + "' typed!");
	}
	public synchronized void mouseEntered( MouseEvent e ) {
	}
	public synchronized void mouseExited( MouseEvent e ) {
	}
	public synchronized void mouseClicked( MouseEvent e ) {
	}


	public synchronized void mousePressed(MouseEvent e) {
		mouse_x = e.getX();
		mouse_y = e.getY();

		// multitouchFramework.requestRedraw();
	}

	public synchronized void mouseReleased(MouseEvent e) {
		mouse_x = e.getX();
		mouse_y = e.getY();

		// multitouchFramework.requestRedraw();
	}


	public synchronized void mouseDragged(MouseEvent e) {

		mouse_x = e.getX();
		mouse_y = e.getY();

		// multitouchFramework.requestRedraw();
	}


	public synchronized void mouseMoved(MouseEvent e) {
		mouse_x = e.getX();
		mouse_y = e.getY();

		// multitouchFramework.requestRedraw();
	}


	public synchronized void processMultitouchInputEvent( int id, float x, float y, int type ) {
		//System.out.println("event: "+id+", "+x+", "+y+", "+type);
		int cursorIndex = cursorContainer.updateCursorById( id, x, y );

//		if ( isCameraModeActive ) {
		if ( type == MultitouchFramework.TOUCH_EVENT_UP ) {
			// up event
			cursorContainer.removeCursorByIndex( cursorIndex );
			
			//CHECK (2 UP en peu de temps dans la zone de mise)
			
			//MISE (1 UP 
		}
//		
		else if ( type == MultitouchFramework.TOUCH_EVENT_MOVE ) {
			
//			while(cursorContainer.getNumCursors() > 0){
//			for(int index = 0; index < cursorContainer.getNumCursors(); index++){
//				Component temp = pokerFrame.getContentPane().getComponent(0).getComponentAt((int)cursorContainer.getCursorByIndex(0).getCurrentPosition().x(), 
//						(int)cursorContainer.getCursorByIndex(0).getCurrentPosition().y());
//				System.out.println(pokerFrame.getContentPane().getComponent(0).getComponentAt((int)cursorContainer.getCursorByIndex(0).getCurrentPosition().x(), 
//						(int)cursorContainer.getCursorByIndex(0).getCurrentPosition().y()).getName());
//			}
//			}
//			if(temp != null){
//				System.out.println("Recognized "+temp.toString());
//				MouseEvent m1 = new MouseEvent(temp,MouseEvent.MOUSE_DRAGGED,System.currentTimeMillis(),0,
//						(int)cursorContainer.getCursorByIndex(0).getCurrentPosition().x(),
//						(int)cursorContainer.getCursorByIndex(0).getCurrentPosition().y(),
//						1,
//						false);
//				temp.dispatchEvent(m1);
//			}
			if ( cursorContainer.getNumCursors() == 2 ) {
				System.out.println("2");
				MyCursor cursor0 = cursorContainer.getCursorByIndex( 0 );
				MyCursor cursor1 = cursorContainer.getCursorByIndex( 1 );
				gw.panAndZoomBasedOnDisplacementOfTwoPoints(
					id==cursor0.id ? cursor0.getPreviousPosition() : cursor0.getCurrentPosition(),
					id==cursor1.id ? cursor1.getPreviousPosition() : cursor1.getCurrentPosition(),
					cursor0.getCurrentPosition(),
					cursor1.getCurrentPosition()
				);
			}
			else if ( cursorContainer.getNumCursors() == 1 ) {
				MyCursor cursor = cursorContainer.getCursorByIndex( 0 );
				gw.pan(
					cursor.getCurrentPosition().x() - cursor.getPreviousPosition().x(),
					cursor.getCurrentPosition().y() - cursor.getPreviousPosition().y()
				);
			}
		}
//		}
//		else {
//
//			if ( type == MultitouchFramework.TOUCH_EVENT_UP ) {
//				// up event
				
//				MyCursor cursor = cursorContainer.getCursorByIndex( cursorIndex );
//				if ( cursor.doesDragLookLikeLassoGesture() ) {
//					ArrayList< Soldier > soldiersInPolygon = game.findSoldiersInPolygon( cursor.getPositions(), gw );
//
//					// Count the number of soldiers there are of each army in the polygon
//					int [] numSoldiersOfEachArmy = new int[ Constant.NUM_ARMIES ];
//					for ( int i = 0; i < Constant.NUM_ARMIES; ++i )
//						numSoldiersOfEachArmy[i] = 0;
//					for ( Soldier soldier : soldiersInPolygon ) {
//						numSoldiersOfEachArmy[ game.armies.indexOf(soldier.army) ] ++;
//					}
//					// Now find which army has the most soldiers in the polygon.
//					int indexOfArmyWithMostSoldiers = 0;
//					int maxNumSoldiersOfASingleArmy = 0;
//					for ( int i = 0; i < Constant.NUM_ARMIES; ++i ) {
//						if ( numSoldiersOfEachArmy[i] > maxNumSoldiersOfASingleArmy ) {
//							indexOfArmyWithMostSoldiers = i;
//							maxNumSoldiersOfASingleArmy = numSoldiersOfEachArmy[i];
//						}
//					}
//
//					if ( maxNumSoldiersOfASingleArmy > 0 )
//						game.armies.get(indexOfArmyWithMostSoldiers).setSelectedSoldiers( soldiersInPolygon );
//				}
//				else { // It wasn't a lasso gesture, it was a drag gesture.
//
//					// Find which army's selected set the gesture started in.
//					for ( Army army : game.armies ) {
//						if (
//							Point2DUtil.isPointInsidePolygon(
//								army.computePolygonEnclosingSelectedSoldiers(),
//								gw.convertPixelsToWorldSpaceUnits(cursor.getPositions().get(0))
//							)
//						) {
//							army.setTargetPositionOfSelectedSoldiers( gw.convertPixelsToWorldSpaceUnits(cursor.getCurrentPosition()) );
//						}
//					}
//				}
//
//
//				cursorContainer.removeCursorByIndex( cursorIndex );
//			}
//		}
		multitouchFramework.requestRedraw();
	}



	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		if ( source == testMenuItem1 ) {
			System.out.println("testMenuItem1 has been selected");
		}
		else if ( source == testMenuItem2 ) {
			System.out.println("testMenuItem2 has been selected");
		}
		else if ( source == autoZoomCheckBox ) {
			isAutoZoomEnabled = ! isAutoZoomEnabled;
		}
		else if ( source == cameraModeCheckBox ) {
			isCameraModeActive = ! isCameraModeActive;
		}
		else if ( source == pauseCheckBox ) {
			isGamePaused = ! isGamePaused;
		}
		else if ( source == frameAllButton ) {
			//gw.frame( game.getBoundingRectangle(), true );
		}
		else if ( source == testButton1 ) {
			System.out.println("testButton1 has been selected");
		}
		else if ( source == testButton2 ) {
			System.out.println("testButton2 has been selected");
		}
	}


}


